package br.com.pontoclass.primes;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import br.com.pontoclass.patterns.PrimeNumberListener;
import br.com.pontoclass.patterns.SimpleNumberListener;
import br.com.pontoclass.patterns.Stoppable;
import br.com.pontoclass.patterns.StoppablePrimeNumberListener;
import br.com.pontoclass.patterns.StoppableSimpleNumberListener;


public class SubscriptionBasedDestinationList implements DestinationList{
    
    public static DestinationList newInstance(){
        return new SubscriptionBasedDestinationList();
    }

    private List<PrimeNumberListener> primeNumberListeners = new ArrayList<>();
    private List<SimpleNumberListener> simpleNumberListeners = new ArrayList<>();

    public void addPrimeNumberListener(PrimeNumberListener pnl) {
        if(pnl != null) {
            if(pnl instanceof StoppablePrimeNumberListener) {
                this.primeNumberListeners.add(new ThreadBasedPrimeNumberListener(StoppablePrimeNumberListener.class.cast(pnl)));
            } else {
                this.primeNumberListeners.add(pnl);
            }
        }
    }
    
    public void addSimpleNumberListener(SimpleNumberListener snl) {
        if(snl != null) {
            if(snl instanceof StoppableSimpleNumberListener) {
                this.simpleNumberListeners.add(new ThreadBasedSimpleNumberListener(StoppableSimpleNumberListener.class.cast(snl)));
            } else {
                this.simpleNumberListeners.add(snl);
            }
        }
    }
    
    public void setPrimeNumberListeners(List<PrimeNumberListener> pnls) {
        if(pnls != null) {
            for(PrimeNumberListener listener: pnls) {
                this.addPrimeNumberListener(listener);
            }
        }
    }
    
    public void setSimpleNumberListeners(List<SimpleNumberListener> snls) {
        if(snls != null) {
            for(SimpleNumberListener listener: snls) {
                this.addSimpleNumberListener(listener);
            }
        }
    }
    
    @Override
    public void addPrime(BigInteger prime) {
        for(PrimeNumberListener listener: primeNumberListeners) {
            try {
                listener.onAddPrime(prime);
            } catch(Throwable e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void addSimple(BigInteger simple) {
        for(SimpleNumberListener listener: simpleNumberListeners) {
            try {
                listener.onAddSimple(simple);
            } catch(Throwable e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void finish() {
        for(PrimeNumberListener listener: primeNumberListeners) {
            if(listener instanceof Stoppable) {
                Stoppable.class.cast(listener).stop();
            }
        }
        for(SimpleNumberListener listener: simpleNumberListeners) {
            if(listener instanceof Stoppable) {
                Stoppable.class.cast(listener).stop();
            }
        }
    }
}